<!--
 * @Author: your name
 * @Date: 2022-10-28 09:10:42
 * @LastEditTime: 2023-03-13 12:22:27
 * @LastEditors: yuhan
 * @Description: sql脚本
 * @FilePath: \apiadmin\src\views\sqlScript\index.vue
-->
<template>
  <div class="sql-script">
    <el-card class="box-card bottom-in">
      <template #header>
        <div class="card-header">
          <div>
            <el-button class="button" type="primary" :icon="Plus" @click="handleEdit('create')"
              >新建</el-button
            >
          </div>
          <div>
            <RefreshBtn />
          </div>
        </div>
      </template>
      <div class="card-content" v-if="dataTable.data.length > 0" v-loading="dataTable.loading">
        <el-table :data="dataTable.data" border style="width: 100%">
          <el-table-column prop="id" label="ID" align="center" width="80">
            <template #default="scope"> {{ scope.row.id || "-" }} </template>
          </el-table-column>
          <el-table-column prop="name" label="名称" align="center" min-width="160">
            <template #default="scope"> {{ scope.row.name || "-" }} </template>
          </el-table-column>
          <el-table-column prop="sourceId" label="数据源" align="center" min-width="160">
            <template #default="scope">
              {{ getDataSourceLabel(scope.row.sourceId) }}
            </template>
          </el-table-column>
          <el-table-column prop="script" label="脚本" align="center" min-width="160">
            <template #default="scope"> {{ scope.row.script || "-" }} </template>
          </el-table-column>
          <el-table-column prop="updatedTime" label="修改时间" width="200px" align="center">
            <template #default="scope">
              {{ formatTime(scope.row.updatedTime, "YYYY-MM-DD hh:mm:ss") }}
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" width="150px" fixed="right">
            <template #default="scope">
              <el-button type="primary" size="small" @click="handleEdit('update', scope.row)"
                >编辑</el-button
              >
              <el-popconfirm title="确定删除?" @confirm="handleEdit('delete', scope.row)">
                <template #reference>
                  <el-button plain size="small">删除</el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          layout="sizes, prev, pager, next, total"
          background
          :current-page="dataTable.pageNo"
          v-model:page-size="dataTable.pageSize"
          :page-sizes="[10, 20, 30, 40]"
          :total="dataTable.total"
          @size-change="
            (pageSize) => {
              dataTable.pageNo = 1; // 重置到第一页
              dataTable.pageSize = pageSize;
              getTableData();
            }
          "
          @current-change="
            (pageNo) => {
              dataTable.pageNo = pageNo;
              getTableData();
            }
          "
        />
      </div>
      <el-empty v-else description="暂无数据" v-loading="dataTable.loading" />
    </el-card>
    <el-dialog
      class="editDialog"
      v-model="editDialog.visible"
      :title="getEditDialogTitle"
      width="820px"
      center
      :close-on-click-modal="false"
      :before-close="closeEditDialog"
    >
      <el-form
        ref="dataForm"
        class="dataForm"
        :model="editDialog.formData"
        status-icon
        :rules="editDialog.rules"
        label-width="100px"
      >
        <el-form-item :label="`${page_config.formItem.name.name}`" prop="name">
          <el-input
            v-model="editDialog.formData.name"
            :placeholder="page_config.formItem.name.placeholder"
            clearable
          />
        </el-form-item>
        <el-form-item :label="`${page_config.formItem.sourceId.name}`" prop="sourceId">
          <el-select
            style="width: 100%"
            v-model="editDialog.formData.sourceId"
            collapse-tags
            collapse-tags-tooltip
          >
            <el-option
              v-for="item in dataSourceDataList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item :label="`${page_config.formItem.script.name}`" prop="script">
          <CodeMirror
            v-if="editDialog.visible"
            :code="editDialog.formData.script"
            codeType="sql"
            @changecb="(val) => (editDialog.formData.script = val)"
            style="width: 100%; height: 300px"
          />
        </el-form-item>
        <!-- 处理结果 -->
        <el-form-item :label="`处理结果`">
          <json-viewer
            v-if="editDialog.formData.testData"
            :value="editDialog.formData.testData"
            :expand-depth="5"
            copyable
            boxed
            :show-array-index="false"
            sort
          ></json-viewer>
          <span v-else style="color: #a8abb2">请要求填写信息后,点击测试按钮进行处理</span>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <div>
            <el-button type="success" @click="handleEdit('test', editDialog.formData)"
              >测试</el-button
            >
          </div>
          <div>
            <el-button type="primary" @click="handleSubmit" :loading="editDialog.loading">
              {{ getEditDialogBtnLabel }}
            </el-button>
            <el-button @click="closeEditDialog"> 取消 </el-button>
          </div>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { Plus } from "@element-plus/icons-vue";
import { ref, onMounted, computed } from "vue";
import { getFormDataUrl, formatTime } from "@/utils/index.js";
import apiUrl from "@/config/api.mjs";
import pageconfig from "@/config/pageConfig.js";
import { ElMessage, ElLoading } from "element-plus";
import { useStore } from "vuex";
import CodeMirror from "@/components/codemirror/index.vue";
import JsonViewer from "vue-json-viewer";
import RefreshBtn from "@/components/RefreshBtn/index.vue";
const store = useStore();
// 页面api
const apis = apiUrl.sqlScript;
// 页面配置
const page_config = pageconfig.sqlScript_config;
// 表单ref
const dataForm = ref("");
// 表格
const dataTable = ref({
  loading: false,
  projectId: "",
  pageNo: 1,
  pageSize: 10,
  total: 0,
  data: [],
});
// 弹框
const editDialog = ref({
  loading: false,
  visible: false,
  editType: "", // create 新增 update 修改
  formData: {},
  rules: {
    name: [
      {
        required: true,
        trigger: "blur",
        message: `请填写${page_config.formItem.name.name}`,
      },
    ],
    sourceId: [
      {
        required: true,
        trigger: "blur",
        message: `请选择${page_config.formItem.sourceId.name}`,
      },
    ],
  },
});
// 弹框标题
const getEditDialogTitle = computed(() => {
  let returnTitle = "";
  switch (editDialog.value.editType) {
    case "create":
      returnTitle = "新建";
      break;
    case "update":
      returnTitle = "修改";
      break;
  }
  return returnTitle;
});
// 弹框底部按钮文案
const getEditDialogBtnLabel = computed(() => {
  let btnLabel = "";
  switch (editDialog.value.editType) {
    case "create":
      btnLabel = "保存";
      break;
    case "update":
      btnLabel = "更新";
      break;
  }
  return btnLabel;
});
// 获取数据列表
const getTableData = () => {
  dataTable.value.loading = true;

  const param = {
    pageNo: dataTable.value.pageNo,
    pageSize: dataTable.value.pageSize,
    projectId: dataTable.value.projectId,
  };
  getFormDataUrl("get", apis.dataList, param)
    .then((res) => {
      if (res) {
        dataTable.value.total = res.total;
        dataTable.value.data = res.records;
      } else {
        ElMessage.warning("res:", res);
      }
    })
    .catch(() => {
      dataTable.value.data = [];
    })
    .finally(() => {
      dataTable.value.loading = false;
    });
};
// 数据源数据列表
const dataSourceDataList = ref([]);
// 获取数据源数据列表
const getDataSourceDataList = () => {
  const param = {
    pageNo: 1,
    pageSize: 999,
    projectId: dataTable.value.projectId,
  };
  getFormDataUrl("get", apiUrl.dataSource.dataList, param).then((res) => {
    if (res.records && res.records.length > 0) {
      dataSourceDataList.value = res.records.map((item) => {
        return {
          value: item.id,
          label: item.name,
        };
      });
    }
  });
};
// 数据源label
const getDataSourceLabel = (id) => {
  let label = "-";
  const target = dataSourceDataList.value.find((item) => item.value === id);
  if (target) {
    label = target.label;
  }
  return label;
};
// 测试
const handleTest = (item) => {
  dataForm.value.validate((valid) => {
    if (valid) {
      const loading = ElLoading.service({
        lock: true,
        text: "Loading",
      });
      const api = apis.test;
      getFormDataUrl("post", `${api}`, {
        dataSourceId: item.sourceId,
        sql: item.script.replace(page_config.codeMirror, "").slice(1), // 过滤掉注释
      })
        .then((res) => {
          editDialog.value.formData.testData = res;
        })
        .catch(() => {})
        .finally(() => {
          loading.close();
        });
    }
  });
};
// 统一操作入口
const handleEdit = (editType, row) => {
  switch (editType) {
    case "search":
      getTableData();
      break;
    case "create":
      editDialog.value.editType = "create";
      openEditDialog();
      break;
    case "update":
      editDialog.value.editType = "update";
      openEditDialog(row);
      break;
    case "delete":
      handleDelete(row.id);
      break;
    case "test":
      handleTest(row);
      break;
    default:
      break;
  }
};

// 初始化编辑框
const initEditDialog = (initformData = "") => {
  const formData = JSON.parse(JSON.stringify(initformData));
  editDialog.value.formData = {
    projectId: dataTable.value.projectId, // 设置为该项目id
    name: formData ? formData.name : "", // 名称
    script: page_config.codeMirror + (formData?.script || ""), // script脚本
    sourceId: formData ? formData.sourceId : "", // 数据源
    testData: "", // 测试结果
  };
  // 更新情况下保存id，接口更新需要
  if (formData) {
    editDialog.value.formData.id = formData.id;
    editDialog.value.formData.createdTime = formData.createdTime;
    editDialog.value.formData.updatedTime = formData.updatedTime;
  }
};
// 打开编辑弹框
const openEditDialog = (formData) => {
  initEditDialog(formData);
  getDataSourceDataList();
  editDialog.value.visible = true;
};
// 关闭编辑弹框
const closeEditDialog = () => {
  dataForm.value.clearValidate();
  editDialog.value.visible = false;
  editDialog.value.title = "";
  initEditDialog();
};
// 新建/修改
const handleSubmit = () => {
  dataForm.value.validate((valid) => {
    if (valid) {
      let api = "";
      if (editDialog.value.formData.script.indexOf(page_config.codeMirror) === -1) {
        ElMessage.error("请勿修改注释");
        return;
      }
      let param = {
        ...editDialog.value.formData,
        script: editDialog.value.formData.script.replace(page_config.codeMirror, ""), // 过滤掉注释
      };
      switch (editDialog.value.editType) {
        case "create":
          api = apis.create;
          break;
        case "update":
          api = apis.update;
          break;
      }
      delete param.testData;
      editDialog.value.loading = true;
      const loading = ElLoading.service({
        lock: true,
        text: "Loading",
      });
      getFormDataUrl("post", api, param)
        .then((res) => {
          ElMessage.success("操作成功");
          closeEditDialog();
          getTableData();
        })
        .finally(() => {
          editDialog.value.loading = false;
          loading.close();
        });
    }
  });
};
// 删除
const handleDelete = (id) => {
  getFormDataUrl("get", `${apis.delete}/${id}`)
    .then((res) => {
      ElMessage.success("操作成功");
      getTableData();
    })
    .finally(() => {});
};

onMounted(() => {
  dataTable.value.projectId = store.getters["project/projectId"];
  handleEdit("search");
  getDataSourceDataList();
});
</script>
<style lang="scss" scoped>
.sql-script {
  .box-card {
    width: 100%;
    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      .input {
        width: 300px;
      }
    }
  }
  .editDialog {
    .dataForm {
      :deep(.el-form-item) {
        align-items: center;
        .el-input-number {
          .el-input__wrapper {
            padding-left: 10px;
            .el-input__inner {
              text-align: left;
            }
          }
        }
      }
      .el-row {
        width: 100%;
        justify-content: space-between;
        margin: 0 0 15px 0;
      }
    }
    .dialog-footer {
      display: flex;
      justify-content: space-between;
    }
  }
}
</style>
